import datetime
import json
from decimal import Decimal

from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.paginator import Paginator
from django.db import transaction
from django.http import HttpResponseForbidden
from django.http import JsonResponse
from django.shortcuts import render

# Create your views here.
from django.utils import timezone
from django.views import View
from django_redis import get_redis_connection

from goods.models import SKU
from orders.models import OrderInfo, OrderGoods
from users.models import Address
from meiduo_mall.utils.response_code import RET


class MyLoginRequiredMiXinView(LoginRequiredMixin, View):
    login_url = "/login/"


class OrderSettlementView(MyLoginRequiredMiXinView):

    def get(self, request):
        addresses_lst = list()

        addresses = request.user.addresses.filter(is_deleted=False)

        for address in addresses:

            mobile = address.mobile

            sre_mobile = mobile.replace(mobile[3:8], "*****")

            address_dict = {"id": address.id,
                            "province": address.province,
                            "district": address.district,
                            "place": address.place,
                            "mobile": sre_mobile,
                            "receiver": address.receiver,
                            "user": request.user}
            addresses_lst.append(address_dict)

        # 获取商品数据
        user = request.user
        skus_list = list()

        redis_conn = get_redis_connection("carts")

        skus_dict = redis_conn.hgetall("cart_%s" % user.id)

        selected_list = redis_conn.smembers("selected_%s" % user.id)

        # 统计总数量
        total_num = 0

        # 统计总金额
        total_amount = 0

        for sku_id in selected_list:

            sku = SKU.objects.get(id=sku_id)

            sku_dict = {"default_image_url":sku.default_image_url.url,
                        "name": sku.name,
                        "price": sku.price,
                        "number": int(skus_dict[sku_id]),
                        "total_amount": sku.price * int(skus_dict[sku_id])}

            skus_list.append(sku_dict)

            total_num += int(skus_dict[sku_id])
            total_amount += (sku.price * int(skus_dict[sku_id]))

        transport_cost = Decimal(10.0)
        sum = total_amount + transport_cost

        calculate = {"total_num": total_num,
                     "total_amount": total_amount,
                     "transport_cost": transport_cost,
                     "sum": sum}

        context = {"addresses": addresses_lst, "skus": skus_list, "calculate":calculate}

        return render(request, "place_order.html", context=context)


# 提交订单处理类视图
class OrderCommitView(MyLoginRequiredMiXinView):

    # 新增事务装饰器
    @transaction.atomic
    def post(self, request):

        # 获取数据
        json_data = json.loads(request.body.decode())

        address_id = json_data.get("address_id")
        pay_method = json_data.get("pay_method")

        user = request.user

        # 校验数据
        # 为空校验
        if not all([address_id, pay_method]):
            return HttpResponseForbidden("参数不全...")

        # 地址校验
        try:
            address = Address.objects.get(id=address_id)

        except Exception as e:
            return HttpResponseForbidden("收货地址不存在...")

        # 支付方式校验
        if int(pay_method) not in OrderInfo.PAY_METHODS_ENUM.values():
            return HttpResponseForbidden("支付方式不正确...")

        # 数据入库
        # 构建订单号
        order_id = timezone.now().strftime("%Y%m%d%H%M%S") + "%06d" % user.id

        # 创建订单状态
        if pay_method == OrderInfo.PAY_METHODS_ENUM["CASH"]:
            status = OrderInfo.ORDER_STATUS_ENUM["UNPAID"]

        else:
            status = OrderInfo.ORDER_STATUS_ENUM["UNSEND"]

        # 开启事务
        sid = transaction.savepoint()
        new_order = OrderInfo.objects.create(order_id=order_id,
                                 total_count=0,
                                 total_amount=0,
                                 freight=Decimal(10),
                                 pay_method=pay_method,
                                 status=status,
                                 address_id=address_id,
                                 user_id=user.id)

        redis_conn = get_redis_connection("carts")

        cart_dict = redis_conn.hgetall("cart_%s" % user.id)

        selected_list = redis_conn.smembers("selected_%s" % user.id)

        total_count = 0
        total_amount = 0

        for sku_id in selected_list:
            while True:

                # 获取sku对象
                sku = SKU.objects.get(id=sku_id)

                # 查看库存数量是否充足
                if sku.stock < int(cart_dict[sku_id]):
                    transaction.savepoint_rollback(sid)
                    return HttpResponseForbidden("商品库存不足...")

                # 模拟并发下单
                import time
                time.sleep(5)

                order_good = OrderGoods()
                order_good.count = cart_dict[sku_id]
                order_good.price = int(cart_dict[sku_id]) * sku.price
                order_good.order_id = order_id
                order_good.sku_id = sku_id
                order_good.save()

                # 统计总数
                total_count += int(cart_dict[sku_id])
                total_amount += order_good.price

                # TODO 乐观锁解决并发问题
                # 修改SKU表的库存

                # 数据准备
                old_stock = sku.stock
                old_sales = sku.sales

                new_stock = old_stock - int(cart_dict[sku_id])
                new_sales = old_sales + int(cart_dict[sku_id])
                ret = SKU.objects.filter(id=sku_id, stock=old_stock).update(stock=new_stock, sales=new_sales)

                if not ret:
                    # transaction.savepoint_rollback(sid)
                    # return HttpResponseForbidden("系统繁忙...")
                    continue

                break

        # 更新订单的商品数量以及总价
        new_order.total_count = total_count
        new_order.total_amount = total_amount + new_order.freight
        new_order.save()
        transaction.savepoint_commit(sid)

        # 删除redis中的数据
        redis_conn.hdel("cart_%s" % user.id, *selected_list)
        redis_conn.srem("selected_%s" % user.id, *selected_list)

        # 返回响应
        return JsonResponse({"code": RET.OK, "errmsg": "success", "order_id": order_id})


class OrderSuccessView(MyLoginRequiredMiXinView):

    def get(self, request):

        order_id = request.GET.get("order_id")
        payment_amount = request.GET.get("payment_amount")
        payment_method = request.GET.get("pay_method")

        context = {"total_amount": payment_amount,
                   "order_id": order_id,
                   "payment_method": payment_method}

        return render(request, "order_success.html", context=context)


class OrderInfoView(MyLoginRequiredMiXinView):

    def get(self, request, page_num):

        # 获取订单内容
        user = request.user

        orders = user.orders.order_by("-create_time")

        paginator = Paginator(orders, 5)

        page = paginator.page(page_num)

        page_order = page.object_list

        total_page_num = paginator.num_pages

        current_page = page.number

        for order in page_order:
            order.order_status = OrderInfo.ORDER_STATUS_CHOICES[order.status - 1][1]
            order.order_id = str(order.order_id)

        context = {"orders": page_order, "total_page_num": total_page_num, "current_page": current_page}

        return render(request, "user_center_order.html", context=context)


class OrderCommentView(MyLoginRequiredMiXinView):
    def get(self, request):

        return render(request, "goods_judge.html")


class JSOrderCommentView(View):

    def get(self, request, order_id):

        try:
            order = OrderInfo.objects.get(order_id=order_id)

        except Exception as e:
            return HttpResponseForbidden("查无此订单...")

        skus = list()

        for good in order.skus.filter(is_commented=False):

            good_dict = {"default_image_url": good.sku.default_image_url.url,
                         "name": good.sku.name,
                         "price": str(good.sku.price),
                         "score": good.score,

                         'order_id': order.order_id,
                         'sku_id': good.sku.id,
                         'comment': good.comment,
                         'is_anonymous': str(good.is_anonymous),
                         }

            skus.append(good_dict)

        return JsonResponse({"skus": skus})


class ChangeCommentView(MyLoginRequiredMiXinView):
    def post(self, request, order_id):

        json_data = json.loads(request.body.decode())

        sku_id = json_data.get("sku")
        comment = json_data.get("comment")
        score = json_data.get("score")
        is_anonymous = json_data.get("is_anonymous")

        if not all([order_id, sku_id, comment, score]):
            return HttpResponseForbidden("参数不全...")

        order = OrderInfo.objects.get(order_id=order_id)

        good = order.skus.filter(sku_id=sku_id)[0]

        good.comment = comment
        good.is_commented = True
        good.score = score
        good.is_anonymous = is_anonymous
        good.save()

        order.status = 5
        order.save()

        return JsonResponse({})